package com.itheima.mp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.itheima.mp.domain.dto.PageDTO;
import com.itheima.mp.domain.po.Address;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.query.UserQuery;
import com.itheima.mp.domain.vo.AddressVO;
import com.itheima.mp.domain.vo.UserVO;
import com.itheima.mp.enums.UserStatus;
import com.itheima.mp.mapper.UserMapper;
import com.itheima.mp.service.IUserService;
import org.springframework.stereotype.Service;

import java.security.Provider;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements IUserService {
    //注入usermapper
    //注入bashmapper
    //直接调用自己方法
    @Override
    public void deductBalance(Long id, Integer money) {
        // 1.查询用户
        User user = getById(id);
        // 2.判断用户状态
        if (user == null || user.getStatus() == UserStatus.FREEZE) {
            throw new RuntimeException("用户状态异常");
        }
        // 3.判断用户余额
        if (user.getBalance() < money) {
            throw new RuntimeException("用户余额不足");
        }
        // 4.扣减余额
        int remainBalance=user.getBalance()-money;
        //baseMapper.deductBalance(id, money);
        lambdaUpdate()
                .set(User::getBalance,remainBalance)
                .set(remainBalance==0,User::getStatus,UserStatus.FREEZE)
                .eq(User::getId,id)
                .eq(User::getBalance,user.getBalance())
                .update();
    }

    //两个泛型
    //用到的mapper
    //操作实体
    //


    @Override
    public UserVO queryUserAndAddressById(Long id) {
        // 1.查询用户
        User user = getById(id);//自己service内部可以直接调用
        if (user == null) {
            return null;
        }

        //复杂查询要用lambdaQuery,调用lambdaQuery要用address的iservice
        //防止循环注入，使用工具类Db代替

        // 2.查询收货地址
        List<Address> addresses = Db.lambdaQuery(Address.class)
                .eq(Address::getUserId, id)
                .list();
        // 3.处理vo
        UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
        if(CollUtil.isNotEmpty(addresses)){
            //List<AddressVO> addressVOS = BeanUtil.copyToList(addresses, AddressVO.class);//返回的是一个vo集合

            userVO.setAddresses(BeanUtil.copyToList(addresses, AddressVO.class));//不需要返回，直接set进去
        }
        return userVO;
    }

    @Override
    public List<UserVO> queryUserAndAddressByIds(List<Long> ids) {
        List<User> users = listByIds(ids);
        if (CollUtil.isNotEmpty(users)) {
            return null;
        }
        // 2.查询收货地址
        // 2.1.获取用户id集合
        //这里不直接用ids的原因是ids有可能不合法

        //由于不可以直接用id查询，要用in()查询，所以要先得到user的id集合
        //不直接用前端给的原因是前端给的可能不一定全是真的，查出来的才是真的
        //这里就是返回一个集合，可以自己for添加的做
        List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());
        //2.2根据用户id查询地址


        List<Address> addresses = Db.lambdaQuery(Address.class)
                .in(Address::getUserId, userIds)
                .list();
        //2.3转换地址VO
        List<AddressVO> addressVOList = BeanUtil.copyToList(addresses, AddressVO.class);
        //2.4梳理地址集合，分类整理，相同用户放入一个集合
        Map<Long,List<AddressVO>> addressMap=new HashMap<>(0);
        if(CollUtil.isNotEmpty(addressVOList)){
            addressMap=addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));
        }

        List<UserVO> userVOS = new ArrayList<>(users.size());
        for (User user:users) {
            //1.
            UserVO vo = BeanUtil.copyProperties(user, UserVO.class);
            userVOS.add(vo);
            vo.setAddresses(addressMap.get(user.getId()));
        }
        return userVOS;
    }

    @Override
    public PageDTO<UserVO> queryUsersPage(UserQuery query) {
        // 1.构建条件
        // 1.1.分页条件
        Page<User> page = Page.of(query.getPageNo(), query.getPageSize());
        //可用lambda简化

        // 1.2.排序条件
        if (query.getSortBy() != null) {
            page.addOrder(new OrderItem(query.getSortBy(), query.getIsAsc()));
        }else{
            // 默认按照更新时间排序
            page.addOrder(new OrderItem("update_time", false));
        }

        // 2.查询
        page(page);
        // 3.数据非空校验
        List<User> records = page.getRecords();
        if (records == null || records.size() <= 0) {
            // 无数据，返回空结果
            return new PageDTO<>(page.getTotal(), page.getPages(), Collections.emptyList());
        }
        // 4.有数据，转换
        List<UserVO> list = BeanUtil.copyToList(records, UserVO.class);
        // 5.封装返回
        return new PageDTO<UserVO>(page.getTotal(), page.getPages(), list);
    }
}

//如果是简单条件的查询建议使用IService里的方法
//如果是复杂条件的查询建议使用lambda表达式
//lambda有复杂更新和复杂查询，查询有单个和多个